﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace CommandLists.Controls
{
    public partial class TactBar : UserControl
    {
        #region Private fields
        private int titleWidth = 50;
        private int tactWidth = 102;
        private int currentTact = 0;
        private int firstVisibleTact = 0;
        private int tactNumber = 1;
        private string title = "Такты"; 
        #endregion

        #region Public properties
        /// <summary>
        /// Ширина области в левой стороне контрола, где располагается заголовок
        /// </summary>
        public int TitleWidth
        {
            get
            {
                return titleWidth;
            }
            set
            {
                if ((value <= 1) || (value > Width - 1))
                    throw new IndexOutOfRangeException("TitleWidth value must be between 10 and Width-10!");

                titleWidth = value;
                MinimumSize = new Size(value + 1, Height);

                Refresh();
            }
        }

        /// <summary>
        /// Текст, который отображается в левой стороне контрола.
        /// </summary>
        public string Title
        {
            get { return title; }
            set { title = value; Refresh(); }
        }

        /// <summary>
        /// Ширина такта
        /// </summary>
        public int TactWidth
        {
            get { return tactWidth; }
            set
            {
                if (value <= 1)
                    throw new IndexOutOfRangeException("TactWidth value must be greater than one!");

                tactWidth = value;

                Refresh();
            }
        }

        /// <summary>
        /// Текущий такт, местоположение курсора
        /// </summary>
        public int CurrentTact
        {
            get { return currentTact; }
            set
            {
                if (value < 0)
                    throw new IndexOutOfRangeException("CurrentTact value must be greater than 0!");

                currentTact = value;

                Refresh();
            }
        }

        /// <summary>
        /// Номер первого отображаемого такта
        /// </summary>
        public int FirstVisibleTact
        {
            get { return firstVisibleTact; }
            set
            {
                if ((value < 0))
                    throw new ArgumentOutOfRangeException("FirstVisibleTact value must be greater than 0!");

                firstVisibleTact = value;

                Invalidate();
            }
        }

        /// <summary>
        /// Кить, которой будет рисоваться курсор
        /// </summary>
        public Pen CursorPen { get; set; }

        /// <summary>
        /// Количество тактов в линейке тактов
        /// </summary>
        public int TactNumber
        {
            get { return tactNumber; }
            set
            {
                if (value < 1)
                    throw new IndexOutOfRangeException("FirstVisibleTact value must be greater than 0!");

                tactNumber = value;

                if (CurrentTact >= tactNumber)
                    CurrentTact = 0;

                if (FirstVisibleTact >= tactNumber)
                    FirstVisibleTact = 0;

                Refresh();
            }
        }

        /// <summary>
        /// Количество тактов, способных одновременно поместиться на данной линейке тактов
        /// </summary>
        public int VisibleTactsCount
        {
            get
            {
                return (Width - TitleWidth) / TactWidth;
            }
        } 
        #endregion

        public TactBar()
        {
            InitializeComponent();
            CursorPen = new Pen(Color.Coral, 4);
            Refresh();
        }

        private void TactBar_Paint(object sender, PaintEventArgs e)
        {
            //общий фон
            e.Graphics.FillRectangle(new LinearGradientBrush(
                    new Rectangle(0, 0, TitleWidth, Height),
                    SystemColors.Highlight,
                    SystemColors.InactiveCaptionText,
                    LinearGradientMode.Vertical)
                , new Rectangle(0, 0, TitleWidth, Height));
            
            //рисуем заголовок
            e.Graphics.DrawString(Title, new Font(FontFamily.GenericSansSerif, 8), Brushes.Black, 2, 1);

            //рисуем фон линейки
            e.Graphics.FillRectangle(new LinearGradientBrush(
                    new Rectangle(TitleWidth, 0, Width - TitleWidth, Height),
                    Color.FromArgb(150, 200, 210, 255),
                    Color.GhostWhite,
                    LinearGradientMode.Vertical)
                    , new Rectangle(TitleWidth, 0, Width - TitleWidth, Height));
            e.Graphics.DrawRectangle(new Pen(Color.Black, 1), new Rectangle(TitleWidth, -1, Width - TitleWidth, Height));

            //рисуем саму линейку
            var tactPen = new Pen(Color.Gray, 1);
            for (int i = 0; i < Math.Min(VisibleTactsCount, TactNumber); i++)
            {
                e.Graphics.DrawLine(
                    tactPen, 
                    new Point(TitleWidth + TactWidth * i, 0),
                    new Point(TitleWidth + TactWidth * i, Height));
                
                e.Graphics.DrawString((i + firstVisibleTact + 1).ToString(),
                    new Font(FontFamily.GenericSansSerif, 8),
                    Brushes.Gray, TitleWidth + TactWidth * i + 2, 1);
            }

            //рисуем текущий такт
            e.Graphics.DrawLine(
                    CursorPen,
                    new Point(TitleWidth + TactWidth * (CurrentTact - FirstVisibleTact) + 2, 0),
                    new Point(TitleWidth + TactWidth * (CurrentTact - FirstVisibleTact) + 2, Height));

            //рисуем левую границу линейки
            e.Graphics.DrawLine(
                    new Pen(Color.Black, 1),
                    new Point(TitleWidth, 0),
                    new Point(TitleWidth, Height));
        }

        private void TactBar_Resize(object sender, EventArgs e)
        {
            var viscount = Math.Min(TactNumber, (Width - TitleWidth) / TactWidth);
            if ((FirstVisibleTact + viscount) > TactNumber)
                FirstVisibleTact = TactNumber - viscount;
        }
    }
}
